// Copyright (c) 2023 Presto Labs Pte. Ltd.
// Author: tianqiang
#pragma once

#include <string>
#include <vector>

#include "coin2/exchange/base/symbology/derivative_util.h"
#include "coin2/exchange/base/symbology/spot_product.h"
#include "coin2/exchange/bitmart/symbology/currency.h"

namespace coin2::exchange::bitmart::symbology {
using ExchangeType = base::market::ExchangeType;
using coin2::exchange::bitmart::symbology::BitmartCurrency;

class BitmartProduct : public base::symbology::SpotProduct<BitmartCurrency, BitmartProduct>,
                       public base::symbology::ProductFromStrMixin<BitmartProduct> {
 public:
  typedef struct {
    bool success;
    std::unique_ptr<BitmartCurrency> base;
    std::unique_ptr<BitmartCurrency> quote;
  } result_t;

  BitmartProduct(const BitmartCurrency& base, const BitmartCurrency& quote)
      : SpotProduct(
            base,
            quote,
            ToBitmartNativeProduct(base, quote),
            ToBitmartNativeProduct(base, quote),
            ExchangeType::Bitmart) {}

 public:
  static std::unique_ptr<BitmartProduct> FromNativeStrImpl(
      const std::string& native_product,
      int64_t resolve_timestamp) {
    auto [success, base, quote] = ParseBitmartNativeProduct(native_product, resolve_timestamp);
    if (success) {
      return std::make_unique<BitmartProduct>(*base, *quote);
    } else {
      return {};
    }
  }

  static result_t ParseBitmartNativeProduct(
      const std::string& product_str,
      int64_t resolve_timestamp) {
    result_t result;

    std::vector<std::string> splitted = Split(product_str, "_");

    if (splitted.size() != 2) {
      result.success = false;
      return result;
    }

    std::string base = splitted[0];
    std::string quote = splitted[1];

    result.success = true;
    result.base = BitmartCurrency::FromNativeStrNoThrow(base, resolve_timestamp);
    result.quote = BitmartCurrency::FromNativeStrNoThrow(quote, resolve_timestamp);
    return result;
  }

  static std::string ToBitmartNativeProduct(
      const BitmartCurrency& base,
      const BitmartCurrency& quote) {
    using base::market::MarketType;
    return base.native_currency(MarketType::Spot) + "_" + quote.native_currency(MarketType::Spot);
  }
};

}  // namespace coin2::exchange::bitmart::symbology
